﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Valhalla
{
    class Disassembler
    {
        public static string Disassemble(Emulator.GBCart memory, int offset, DisassembleFlags flags, out int length)
        {
            ProcessorOperation operation;
            byte operationCode, extraByte1, extraByte2;
            ushort data;
            string offsetText, rawDataText, opcodeText;
            string formatString;

            if (flags == DisassembleFlags.Instruction)
                formatString = "{2}";
            else if (flags == DisassembleFlags.Offset)
                formatString = "{0}  {2}";
            else if (flags == DisassembleFlags.Instruction)
                formatString = "{1,-8}  {2}";
            else
                formatString = "{0}  {1,-8}  {2}";

            offsetText = offset.ToString("X4");

            operationCode = memory.ReadByte(offset++);

            rawDataText = operationCode.ToString("X2");

            operation = OperationList.ProcessorOperations[operationCode];
            length = (ushort)(1 + operation.ExtraByteCount);

            if (operation.ExtraByteCount == 1)
            {
                extraByte1 = memory.ReadByte(offset);

                rawDataText += " " + extraByte1.ToString("X2");

                data = extraByte1;
            }
            else if (operation.ExtraByteCount == 2)
            {
                extraByte1 = memory.ReadByte(offset);
                extraByte2 = memory.ReadByte((ushort)(offset + 1));

                rawDataText += " " + extraByte1.ToString("X2") + " " + extraByte2.ToString("X2");

                data = (ushort)(extraByte1 | (extraByte2 << 8));
            }
            else
                data = 0;

            if (operation.FormatString == null || operation.FormatString.Length == 0)
                opcodeText = string.Format("DB ${0:X2}", operationCode);
            else
                opcodeText = string.Format(operation.FormatString, data);

            return string.Format(formatString, offsetText, rawDataText, opcodeText);
        }

        public static string ShowCode(Emulator.GBCart card)
        {
            string code = null;
            int offset = 0x100;
            while (offset < 0x3FFF)
            {
                int x = 0;
                code += Disassemble(card, offset, DisassembleFlags.Default, out x) + Environment.NewLine;
                offset += x;

            }
            return code;
        }
    }
}
